/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
    ArkFile,
    AstTreeUtils,
    ts,
} from 'arkanalyzer';
import { Rule } from '../../Index';
import { BaseChecker, BaseMetaData } from '../BaseChecker';
import { Defects } from '../../Index';
import {
    FileMatcher,
    MatcherCallback,
    MatcherTypes,
} from '../../Index';
import { RuleListUtil } from "../../utils/common/DefectsList";
import { IssueReport } from "../../model/Defects";

interface MessageInfo {
    line: number;
    character: number;
    endCol: number;
    message: string;
}

export class NoUnreachableCheck implements BaseChecker {
    public rule: Rule;
    public defects: Defects[] = [];
    public issues: IssueReport[] = [];
    public metaData: BaseMetaData = {
        severity: 2,
        ruleDocPath: 'docs/no-unreachable-check.md',
        description: 'Disallow unreachable code after `return`, `throw`, `continue`, and `break` statements',
    };

    private fileMatcher: FileMatcher = {
        matcherType: MatcherTypes.FILE,
    };

    public registerMatchers(): MatcherCallback[] {
        const matchFileCb: MatcherCallback = {
            matcher: this.fileMatcher,
            callback: this.check
        }
        return [matchFileCb];
    }

    // 处理控制流语句
    private checkControlFlowStatement(node: ts.Node, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const nextStatement = this.findNextStatement(node);
        if (nextStatement && !ts.isFunctionDeclaration(nextStatement)) {
            this.checkNextStatementAfterControlFlow(nextStatement, node, sourceFile, errors);
        }
    }

    // 检查控制流语句后的下一个语句
    private checkNextStatementAfterControlFlow(nextStatement: ts.Statement,
        node: ts.Node,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        if (!this.isVarDeclarationStmt(nextStatement)) {
            this.addControlFlowError(nextStatement, node, sourceFile, errors);
        }
    }

    // 添加控制流相关的错误
    private addControlFlowError(statement: ts.Statement,
        node: ts.Node,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        const { line, character } = sourceFile.getLineAndCharacterOfPosition(statement.getStart());
        errors.push({
            line: line + 1,
            character: character + 1,
            endCol: character + 1 + node.getText().length,
            message: 'Unreachable code'
        });
    }

    private checkUnreachableCode(fileName: string, code: string): MessageInfo[] {
        const sourceFile = AstTreeUtils.getASTNode(fileName, code);
        const errors: MessageInfo[] = [];
        this.visitAST(sourceFile, sourceFile, errors);
        return errors;
    }

    private visitAST(node: ts.Node, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        if (!node) {
            return;
        }
        
        // Check different node types
        this.processNodeByType(node, sourceFile, errors);
        
        // Continue traversing the AST
        ts.forEachChild(node, child => this.visitAST(child, sourceFile, errors));
    }

    private processNodeByType(node: ts.Node, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        // Check control flow statements
        if (this.isControlFlowEndingStatement(node)) {
            this.checkControlFlowStatement(node, sourceFile, errors);
        }
        
        // Check other node types
        this.checkOtherNodeTypes(node, sourceFile, errors);
    }

    private isControlFlowEndingStatement(node: ts.Node): boolean {
        return ts.isReturnStatement(node) || 
               ts.isThrowStatement(node) ||
               ts.isBreakStatement(node) || 
               ts.isContinueStatement(node);
    }

    private checkOtherNodeTypes(node: ts.Node, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        if (ts.isForStatement(node) && !node.condition) {
            this.checkInfiniteForLoop(node, sourceFile, errors);
        }
        else if (ts.isSwitchStatement(node)) {
            this.checkSwitchStatement(node, sourceFile, errors);
        }
        else if (ts.isIfStatement(node)) {
            this.checkIfStatement(node, sourceFile, errors);
        }
        else if (this.isFunctionNode(node)) {
            this.checkFunctionBody(node, sourceFile, errors);
        }
        else if (ts.isClassDeclaration(node)) {
            this.checkClassDeclaration(node, sourceFile, errors);
        }
        else if (ts.isSourceFile(node) && !ts.isClassDeclaration(node)) {
            this.checkSourceFileStatements(node, sourceFile, errors);
        }
        else if (this.isLoopNode(node)) {
            this.checkLoopStatement(node, sourceFile, errors);
        }
        else if (ts.isTryStatement(node)) {
            this.checkTryStatement(node, sourceFile, errors);
        }
    }

    private isFunctionNode(node: ts.Node): node is ts.FunctionDeclaration | ts.FunctionExpression | ts.ArrowFunction {
        return ts.isFunctionDeclaration(node) || 
               ts.isFunctionExpression(node) || 
               ts.isArrowFunction(node);
    }

    private isLoopNode(node: ts.Node): node is ts.WhileStatement | ts.ForStatement | ts.DoStatement {
        return ts.isWhileStatement(node) || 
               ts.isForStatement(node) || 
               ts.isDoStatement(node);
    }

    private checkInfiniteForLoop(node: ts.ForStatement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const nextStatement = this.findNextStatement(node);
        if (nextStatement && 
            !ts.isFunctionDeclaration(nextStatement) &&
            this.isControlFlowTerminated(nextStatement)) {
            this.addUnreachableCodeError(nextStatement, node, sourceFile, errors);
        }
    }

    private addUnreachableCodeError(
        statement: ts.Statement, 
        node: ts.Node, 
        sourceFile: ts.SourceFile, 
        errors: MessageInfo[]
    ): void {
        const { line, character } = sourceFile.getLineAndCharacterOfPosition(statement.getStart());
        errors.push({
            line: line + 1,
            character: character + 1,
            endCol: character + 1 + node.getText().length,
            message: 'Unreachable code'
        });
    }

    // 处理 if 语句
    private checkIfStatement(node: ts.IfStatement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const thenTerminated = this.isControlFlowTerminated(node.thenStatement);
        const elseTerminated = node.elseStatement ? this.isControlFlowTerminated(node.elseStatement) : false;

        // 如果 if 和 else 都终止了控制流，则检查后续代码
        if (thenTerminated && elseTerminated) {
            this.checkNextStatementAfterIf(node, sourceFile, errors);
        }
    }

    // 检查 if 语句之后的代码
    private checkNextStatementAfterIf(node: ts.IfStatement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const nextStatement = this.findNextStatement(node);
        if (nextStatement && !ts.isFunctionDeclaration(nextStatement)) {
            this.addUnreachableError(nextStatement, sourceFile, errors);
        }
    }

    // 添加不可达错误
    private addUnreachableError(statement: ts.Statement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const { line, character } = sourceFile.getLineAndCharacterOfPosition(statement.getStart());
        errors.push({
            line: line + 1,
            character: character + 1,
            endCol: character + 1 + statement.getText().length,
            message: 'Unreachable code'
        });
    }

    // 检查源文件中的语句
    private checkSourceFileStatements(node: ts.SourceFile, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        let isUnreachable = false; // 标记是否已经遇到控制流终止语句
        for (let i = 0; i < node.statements.length; i++) {
            const currentStatement = node.statements[i];
            this.processSourceFileStatement(currentStatement, sourceFile, errors, isUnreachable);

            // 更新不可达状态
            if (currentStatement && this.isControlFlowTerminated(currentStatement)) {
                isUnreachable = true;
            }
        }
    }

    // 处理源文件中的单个语句
    private processSourceFileStatement(statement: ts.Statement, sourceFile: ts.SourceFile,
        errors: MessageInfo[], isUnreachable: boolean): void {
        if (isUnreachable) {
            this.checkUnreachableSourceStatement(statement, sourceFile, errors);
        }
    }

    // 检查源文件中不可达的语句
    private checkUnreachableSourceStatement(statement: ts.Statement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        if (!this.isValidSourceStatement(statement)) {
            this.handleUnreachableStatement(statement, sourceFile, errors);
        }
    }

    // 检查语句是否为有效的源文件语句
    private isValidSourceStatement(statement: ts.Statement): boolean {
        return ts.isFunctionDeclaration(statement) ||
            ts.isMethodDeclaration(statement) ||
            ts.isClassDeclaration(statement) ||
            ts.isThrowStatement(statement);
    }

    // 处理不可达的语句
    private handleUnreachableStatement(statement: ts.Statement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        let flag = this.isVarDeclarationSForThrowStmt(statement);
        if (!flag) {
            const { line, character } = sourceFile.getLineAndCharacterOfPosition(statement.getStart());
            errors.push({
                line: line + 1,
                character: character + 1,
                endCol: character + 1 + statement.getText().length,
                message: 'Unreachable code'
            });
        }
    }

    // 检查函数体
    private checkFunctionBody(node: ts.FunctionDeclaration | ts.FunctionExpression | ts.ArrowFunction,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        const body = node.body;

        // 处理 body 为 undefined 的情况（例如函数声明没有函数体）
        if (!body) {
            return;
        }

        // 处理箭头函数的简写形式（例如 `() => expr`）
        if (!ts.isBlock(body)) {
            // 如果函数体是表达式，则不需要检查不可达代码
            return;
        }

        this.checkFunctionStatements(body, sourceFile, errors);
    }

    // 检查函数体中的语句
    private checkFunctionStatements(body: ts.Block,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        for (let i = 0; i < body.statements.length; i++) {
            const currentStatement = body.statements[i];
            if (currentStatement && this.isControlFlowTerminated(currentStatement)) {
                // 如果当前语句终止了控制流，检查下一条语句是否不可达
                this.checkNextFunctionStatement(currentStatement, sourceFile, errors);
            }
        }
    }

    // 检查函数中的下一条语句
    private checkNextFunctionStatement(currentStatement: ts.Statement,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        const nextStatement = this.findNextStatement(currentStatement);
        if (nextStatement &&
            !ts.isEmptyStatement(nextStatement) &&
            !ts.isFunctionDeclaration(nextStatement) &&
            !this.isVarDeclarationStmt(nextStatement)) {
            const { line, character } = sourceFile.getLineAndCharacterOfPosition(nextStatement.getStart());
            errors.push({
                line: line + 1,
                character: character + 1,
                endCol: character + 1 + nextStatement.getText().length,
                message: 'Unreachable code'
            });
        }
    }

    // 处理循环语句
    private checkLoopStatement(node: ts.WhileStatement | ts.ForStatement | ts.DoStatement,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        const body = ts.isForStatement(node) ? node.statement : node.statement;
        if (ts.isBlock(body)) {
            this.checkLoopBody(body, node, sourceFile, errors);
        }
    }

    // 检查循环体
    private checkLoopBody(body: ts.Block,
        node: ts.WhileStatement | ts.ForStatement | ts.DoStatement,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        let isUnreachable = false;
        for (const statement of body.statements) {
            // 标记不可达代码
            if (isUnreachable) {
                this.checkUnreachableLoopStatement(statement, sourceFile, errors, node);
            }
            // 判断是否中断循环控制流
            if (this.isBreakOrContinue(statement) || this.isControlFlowTerminated(statement)) {
                isUnreachable = true;
            }
        }
    }

    // 检查循环中不可达的语句
    private checkUnreachableLoopStatement(statement: ts.Statement,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[],
        node: ts.Node): void {
        if (!this.isVarDeclarationStmt(statement)) {
            const { line, character } = sourceFile.getLineAndCharacterOfPosition(statement.getStart());
            errors.push({
                line: line + 1,
                character: character + 1,
                endCol: character + 1 + node.getText().length,
                message: 'Unreachable code'
            });
        }
    }

    // 处理类声明
    private checkClassDeclaration(node: ts.ClassDeclaration, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const classMembers = node.members;
        // 检查是否有继承关系
        const hasExtends = this.checkClassExtends(node);

        // 只有在有继承关系的情况下才检查构造函数中的 super() 调用
        if (hasExtends) {
            this.checkClassConstructor(classMembers, node, sourceFile, errors);
        }
    }

    // 检查类是否有继承关系
    private checkClassExtends(node: ts.ClassDeclaration): boolean {
        return node.heritageClauses?.some(clause =>
            clause.token === ts.SyntaxKind.ExtendsKeyword
        ) ?? false;
    }

    // 检查类的构造函数
    private checkClassConstructor(classMembers: ts.NodeArray<ts.ClassElement>,
        node: ts.ClassDeclaration,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        const constructorE = classMembers.find(member => ts.isConstructorDeclaration(member));
        if (constructorE) {
            // 检查构造函数是否调用了 super()
            const hasSuperCall = this.hasSuperCallInConstructor(constructorE);
            if (!hasSuperCall) {
                this.checkUnreachableInstanceFields(classMembers, node, sourceFile, errors);
            }
        }
    }

    // 检查不可达的实例字段
    private checkUnreachableInstanceFields(classMembers: ts.NodeArray<ts.ClassElement>,
        node: ts.ClassDeclaration,
        sourceFile: ts.SourceFile,
        errors: MessageInfo[]): void {
        // 如果构造函数没有调用 super()，则实例字段是不可达的
        for (const member of classMembers) {
            if (ts.isPropertyDeclaration(member) &&
                !member.modifiers?.some(mod => mod.kind === ts.SyntaxKind.StaticKeyword)) {
                const { line, character } = sourceFile.getLineAndCharacterOfPosition(member.getStart());
                errors.push({
                    line: line + 1,
                    character: character + 1,
                    endCol: character + 1 + node.getText().length,
                    message: 'Unreachable code'
                });
            }
        }
    }

    private checkTryStatement(node: ts.TryStatement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const tryBlock = node.tryBlock;
        const catchClause = node.catchClause;
        const finallyBlock = node.finallyBlock;

        // 检查 try 块中的 return 语句是否会导致 catch 块中的代码不可达
        if (tryBlock && this.isControlFlowTerminated(tryBlock)) {
            this.checkCatchBlockReachability(catchClause, node, sourceFile, errors);
            this.checkNextStatementAfterTry(node, sourceFile, errors);
        }

        // 如果 finally 块存在，检查其中的代码
        if (finallyBlock) {
            this.checkFinallyBlock(finallyBlock, node, sourceFile, errors);
        }
    }

    // 检查 catch 块的可达性
    private checkCatchBlockReachability(catchClause: ts.CatchClause | undefined, node: ts.TryStatement,
        sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        // 标记 catch 块中的代码为不可达
        if (catchClause && catchClause.block) {
            const { line, character } = sourceFile.getLineAndCharacterOfPosition(catchClause.block.getStart());
            errors.push({
                line: line + 1,
                character: character + 1,
                endCol: character + 1 + node.getText().length,
                message: 'Unreachable code'
            });
        }
    }

    // 检查 try 语句之后的代码
    private checkNextStatementAfterTry(node: ts.TryStatement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const nextStatement = this.findNextStatement(node);
        if (nextStatement && !ts.isFunctionDeclaration(nextStatement)) {
            const { line, character } = sourceFile.getLineAndCharacterOfPosition(nextStatement.getStart());
            errors.push({
                line: line + 1,
                character: character + 1,
                endCol: character + 1 + node.getText().length,
                message: 'Unreachable code'
            });
        }
    }

    // 检查 finally 块
    private checkFinallyBlock(finallyBlock: ts.Block, node: ts.TryStatement,
        sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        // 检查 finally 块中的代码是否会导致之后的代码不可达
        if (this.isControlFlowTerminated(finallyBlock)) {
            const nextStatement = this.findNextStatement(node);
            if (nextStatement && !ts.isFunctionDeclaration(nextStatement)) {
                const { line, character } = sourceFile.getLineAndCharacterOfPosition(nextStatement.getStart());
                errors.push({
                    line: line + 1,
                    character: character + 1,
                    endCol: character + 1 + node.getText().length,
                    message: 'Unreachable code'
                });
            }
        }
    }

    private checkSwitchStatement(node: ts.SwitchStatement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        let isSwitchUnreachable = true;
        for (const caseClause of node.caseBlock.clauses) {
            isSwitchUnreachable = this.checkCaseClause(caseClause, sourceFile, errors) && isSwitchUnreachable;
        }

        // 如果 switch 整体不可达，则检查 switch 之后的代码
        if (isSwitchUnreachable) {
            this.checkNextStatementAfterSwitch(node, sourceFile, errors);
        }
    }

    // 处理单个 case 子句
    private checkCaseClause(caseClause: ts.CaseOrDefaultClause, sourceFile: ts.SourceFile, errors: MessageInfo[]): boolean {
        let isCaseUnreachable = false;
        for (let i = 0; i < caseClause.statements.length; i++) {
            const currentStatement = caseClause.statements[i];
            // 如果已经遇到控制流终止语句，则其后的代码都是不可达的
            if (isCaseUnreachable) {
                this.checkUnreachableStatement(currentStatement, sourceFile, errors);
            }

            // 检查当前语句是否终止了控制流
            if (currentStatement && this.isControlFlowTerminated(currentStatement)) {
                isCaseUnreachable = true;
            } else {
                // 如果某个 case 分支没有终止控制流，则 switch 之后的代码可能可达
                return false;
            }
        }
        return true;
    }

    // 检查不可达的语句
    private checkUnreachableStatement(statement: ts.Statement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        if (!this.isVarDeclarationStmt(statement)) {
            const { line, character } = sourceFile.getLineAndCharacterOfPosition(statement.getStart());
            errors.push({
                line: line + 1,
                character: character + 1,
                endCol: character + 1 + statement.getText().length,
                message: 'Unreachable code'
            });
        }
    }

    // 检查 switch 语句后的下一个语句
    private checkNextStatementAfterSwitch(node: ts.SwitchStatement, sourceFile: ts.SourceFile, errors: MessageInfo[]): void {
        const nextStatement = this.findNextStatement(node);
        if (nextStatement && !ts.isEmptyStatement(nextStatement) && !ts.isFunctionDeclaration(nextStatement)) {
            const { line, character } = sourceFile.getLineAndCharacterOfPosition(nextStatement.getStart());
            errors.push({
                line: line + 1,
                character: character + 1,
                endCol: character + 1 + node.getText().length,
                message: 'Unreachable code'
            });
        }
    }

    // 判断是否为 var 声明
    private isVarDeclarationStmt(node: ts.Node): boolean {
        if (ts.isVariableStatement(node)) {
            const declarations = node.declarationList.declarations;
            // 检查是否有任何声明包含初始化器（赋值）
            const hasInitializer = declarations.some(decl => decl.initializer !== undefined);
            let flag = (node.declarationList.flags & ts.NodeFlags.Let) === 0 &&
                (node.declarationList.flags & ts.NodeFlags.Const) === 0 &&
                !hasInitializer; // 只有当没有初始化器时才返回 true
            return flag;
        }
        return false;
    }

    private isVarDeclarationSForThrowStmt(node: ts.Node): boolean {
        if (ts.isVariableStatement(node)) {
            const declarations = node.declarationList.declarations;
            // 检查是否有任何声明包含初始化器（赋值）
            const hasInitializer = declarations.some(decl => decl.initializer !== undefined);
            let flag = (node.declarationList.flags & ts.NodeFlags.Let) === 0 &&
                (node.declarationList.flags & ts.NodeFlags.Const) === 0;
            return flag;
        }
        return false;
    }

    // 查找当前语句之后的下一条语句
    private findNextStatement(node: ts.Node): ts.Statement | undefined {
        const parent = node.parent;
        if (ts.isBlock(parent)) {
            const index = parent.statements.indexOf(node as ts.Statement);
            if (index < parent.statements.length - 1) {
                const nextStmt = parent.statements[index + 1];
                // 如果下一个语句是空语句（分号），则继续查找下一个语句
                if (ts.isEmptyStatement(nextStmt) && index + 2 < parent.statements.length) {
                    return parent.statements[index + 2];
                }
                return nextStmt;
            }
        }
        return undefined;
    }

    // 判断一个语句是否会导致控制流中断
    private isControlFlowTerminated(node: ts.Node | undefined): boolean {
        if (!node) {
            return false;
        }
        // 处理基本控制流语句和块语句
        if (this.isBasicControlFlowTerminator(node)) {
            return true;
        }
        // 处理复杂控制流语句
        return this.isComplexControlFlowTerminator(node);
    }

    // 检查基本的控制流终止语句
    private isBasicControlFlowTerminator(node: ts.Node): boolean {
        // 处理 return、throw、break、continue 语句
        if (ts.isReturnStatement(node) ||
            ts.isThrowStatement(node) ||
            ts.isBreakStatement(node) ||
            ts.isContinueStatement(node)) {
            return true;
        }

        // 处理块语句
        if (ts.isBlock(node)) {
            for (const statement of node.statements) {
                if (this.isControlFlowTerminated(statement)) {
                    return true;
                }
            }
            return false;
        }

        return false;
    }

    // 检查复杂的控制流终止语句
    private isComplexControlFlowTerminator(node: ts.Node): boolean {
        // 处理 ForStatement
        if (ts.isForStatement(node)) {
            if (!node.condition) {
                const bodyTerminated = this.isControlFlowTerminated(node.statement);
                return !bodyTerminated;
            }
            return false;
        }
        // 处理 if 语句
        if (ts.isIfStatement(node)) {
            const thenTerminated = this.isControlFlowTerminated(node.thenStatement);
            const elseTerminated = node.elseStatement ? this.isControlFlowTerminated(node.elseStatement) : false;
            return thenTerminated && elseTerminated;
        }
        // 处理 try-finally 语句
        if (ts.isTryStatement(node)) {
            const tryTerminated = this.isControlFlowTerminated(node.tryBlock);
            const finallyTerminated = node.finallyBlock ? this.isControlFlowTerminated(node.finallyBlock) : false;
            return tryTerminated || finallyTerminated;
        }
        // 处理 do-while 语句
        if (ts.isDoStatement(node)) {
            return this.isControlFlowTerminated(node.statement);
        }
        // 处理 while 语句
        if (ts.isWhileStatement(node)) {
            if (node.expression.kind === ts.SyntaxKind.TrueKeyword) {
                return this.checkInfiniteWhileLoop(node);
            }
            return false;
        }
        // 处理 switch 语句
        if (ts.isSwitchStatement(node)) {
            return this.checkSwitchTermination(node);
        }
        return false;
    }

    // 检查 switch 语句的终止情况
    private checkSwitchTermination(node: ts.SwitchStatement): boolean {
        for (const caseClause of node.caseBlock.clauses) {
            if (this.checkCaseClauseTermination(caseClause)) {
                return true;
            }
        }
        return false;
    }

    // 检查 case 子句的终止情况
    private checkCaseClauseTermination(caseClause: ts.CaseOrDefaultClause): boolean {
        for (const statement of caseClause.statements) {
            if (this.isControlFlowTerminated(statement)) {
                return true;
            }
        }
        return false;
    }

    // 检查无限 while 循环
    private checkInfiniteWhileLoop(node: ts.WhileStatement): boolean {
        if (ts.isBlock(node.statement)) {
            return this.checkInfiniteWhileLoopBlock(node.statement);
        }
        return false;
    }

    // 检查无限 while 循环的代码块
    private checkInfiniteWhileLoopBlock(block: ts.Block): boolean {
        for (const statement of block.statements) {
            if (this.isControlFlowTerminated(statement)) {
                return false;
            }
        }
        return true;
    }

    // 检查构造函数中是否调用了 super(),.../
    private hasSuperCallInConstructor(constructorEle: ts.ClassElement): boolean {
        let hasSuperCall = false;
        function visit(node: ts.Node): void {
            if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.SuperKeyword) {
                hasSuperCall = true;
            }
            ts.forEachChild(node, visit);
        }
        if (constructorEle) {
            ts.forEachChild(constructorEle, visit);
        }
        return hasSuperCall;
    }

    // 添加辅助判断函数
    private isBreakOrContinue(node: ts.Node): boolean {
        return ts.isBreakStatement(node) || ts.isContinueStatement(node);
    }

    public check = (targetField: ArkFile) => {
        const severity = this.rule.alert ?? this.metaData.severity;
        const filePath = targetField.getFilePath();
        let code = targetField.getCode();
        const myInvalidPositions = this.checkUnreachableCode(targetField.getName(), code);
        let myInvalidPositionsNew = this.sortMyInvalidPositions(myInvalidPositions);
        myInvalidPositionsNew.forEach(pos => {
            this.addIssueReport(filePath, pos, severity)
        });
    }

    // 对错误位置进行排序并去重
    private sortMyInvalidPositions(myInvalidPositions: Array<MessageInfo>): MessageInfo[] {
        // 1. 先进行排序
        myInvalidPositions.sort((a, b) => a.line - b.line || a.character - b.character);
        // 2. 使用 reduce 进行去重
        const uniqueArrays = myInvalidPositions.reduce((acc, current) => {
            const lastItem = acc[acc.length - 1];

            // 检查是否与最后一个元素的三要素相同
            if (!lastItem ||
                lastItem.line !== current.line ||
                lastItem.character !== current.character ||
                lastItem.message !== current.message) {
                acc.push(current);
            }
            return acc;
        }, [] as typeof myInvalidPositions);

        return uniqueArrays;
    }

    private addIssueReport(filePath: string, pos: MessageInfo, severity: number) {
        let defect = new Defects(pos.line, pos.character, pos.endCol, pos.message, severity, this.rule.ruleId,
            filePath, this.metaData.ruleDocPath, true, false, false);

        this.issues.push(new IssueReport(defect, undefined));
        RuleListUtil.push(defect);
    }
}